#include "thread.h"
// 没考虑重入，退出后清理
Thread::Thread(): 
    m_tid(0)
    ,m_id(0)
    ,m_pTarget(NULL)
    ,m_stackSize(0)
    ,m_started(false)
    ,m_joined(false)
{
    // m_done使用默认值，自动重置
}

Thread::Thread(const std::string& name): 
    m_tid(0)
    ,m_id(0)
    ,m_name(name)
    ,m_pTarget(NULL)
    ,m_stackSize(0)
    ,m_started(false)
    ,m_joined(false)
{
    // m_done使用默认值，自动重置
}

Thread::~Thread()
{
    if (m_started && !m_joined)
    {
        pthread_detach(m_id);
    }
}

void Thread::start(Runnable& target)
{
    // 已启动
    if (m_pTarget != NULL)
        return;

    pthread_attr_t attributes;
    pthread_attr_init(&attributes);

    if (m_stackSize != 0)
    {
        if (0 != pthread_attr_setstacksize(&attributes, m_stackSize))
        {
            pthread_attr_destroy(&attributes);
            return;
        }
    }

    m_pTarget = &target;

    if (pthread_create(&m_id, &attributes, runnableEntry, this) != 0)
    {
        m_pTarget = NULL;
        pthread_attr_destroy(&attributes);
        return;
    }
    m_started = true;
    pthread_attr_destroy(&attributes);
}

void Thread::join()
{
    if (!m_started) return;

    m_done.wait();
    void* result;
    pthread_join(m_id, &result);
    m_joined = true;
}

bool Thread::join(long milliseconds)
{
    if (m_started && m_done.tryWait(milliseconds))
    {
        void* result;
        if (pthread_join(m_id, &result))
            return false;

        m_joined = true;
    }
    else if (m_started)
        return false;

    return true;
}

bool Thread::tryJoin(long milliseconds)
{
    return join(milliseconds);
}

void* Thread::runnableEntry(void* pThread)
{
    Thread* pself = reinterpret_cast<Thread*>(pThread);
    if (pself == NULL || pself->m_pTarget == NULL)
    {
        pself->m_done.set();
        return NULL;
    }
    
    sigset_t sset;
    sigemptyset(&sset);
    sigaddset(&sset, SIGQUIT);
    sigaddset(&sset, SIGTERM);
    sigaddset(&sset, SIGPIPE); 
    pthread_sigmask(SIG_BLOCK, &sset, 0);

    pself->m_pTarget->run();
    pself->m_pTarget = NULL;
    pself->m_done.set();
    // 不重入，可以不设置m_done.reset();
    // 还是设置m_done自动重置吧
    return NULL;
}




